#!/usr/bin/env python2
# -*- coding: utf-8 -*-
#
# Author: Izidor Matusov
# Patches: Josef Halicek
# Maintance: polo
# 2008-2009

# Constants
# Standard palace for configuration
DEFAULT_CONFIG="~/.norarc"


# Main stone of whole project
import xmpp

# Standard libraries
import inspect # Inspecting class methods

import os
import sys
import re

import ConfigParser

from datetime import datetime, timedelta
from time import mktime, time, localtime

from math import floor
import random

# apo pokus
from dbnora import dbnora

# Local library
import messages

#polove sracky
pole = {}

class noraBot():
	command_prefix = "cmd_"
	command_mark = "!"
	notification = {}
	poloLastActivity = None


        def __init__(self, configFile):
		self.parseConfig(configFile)

		self.cl = None
                self.game = None
                self.command = {}
		self.lastSaid = {}

                for (name, func) in inspect.getmembers(self):
			if inspect.ismethod(func) and name.startswith(self.command_prefix):
                    		self.command[self.command_mark+name[len(self.command_prefix):]] = func

		self.command[self.command_mark + "pochval"] = self.cmd_good
		self.command[self.command_mark + "thx"] = self.cmd_good

		self.automaticMessages = messages.Messages(messages.commandFiles)

                self._database = dbnora.DbNora("zaznamy", "./noradb") # hard coded filename :D

                return

	def parseConfig(self, configFile):
		"""
		Parse 'configFile' which is in format very similar to Windows INI File and set global file
		"""
		if not os.path.isfile(configFile):
			sys.stderr.write("Config file %s does not exist\n"%(configFile))
			exit(1)

		try:
			config = ConfigParser.ConfigParser()
			config.read(configFile)

			self.jid = xmpp.protocol.JID(config.get('Account', 'account'))
			self.passwd = config.get('Account', 'password')

			self.rooms = []
			if config.has_section('muc'):
				self.nick = config.get('Account', 'defaultMucNick')

				pattern = re.compile("([^:]+)(:[^@]+|)(@[^/]*)(/.*|)$")
				for room in config.options('muc'):
					parts = pattern.match(config.get('muc', room))
					roomJID = parts.group(1) + parts.group(3)
					print "###", roomJID
					roomPasswd = parts.group(2)
					roomNick = parts.group(4)[1:]
					if roomNick == "":
						roomNick = self.nick # Usage of the standard one
					print roomNick
					self.rooms.append([roomJID, roomPasswd, roomNick])
		except:
			sys.stderr.write("Problem with parsing config file %s =>\n %s : %s\n"%(configFile, str(sys.exc_type), sys.exc_value))
			exit(1)

	def set_timer(self):
		interval = 60*60
		self.next_update = time() - time()%interval + interval

	def conf_message(self, sender, text):
		conf =  sender.getStripped()
		self.connect().send(xmpp.Message(conf, text, 'groupchat'))

	def cmd_reverse(self, cl, message, args):
		if len(args.split()) >= 1 and args[len(args)-1] != "!" and args.split()[0] != "pleh":
			self.conf_message(message.getFrom(), args[::-1])
	
	def cmd_dobru(self, cl, message, args):
		if len(args.split()) >= 1:
			self.conf_message(message.getFrom(), u"Dobru " + args.split()[0] + u" aj tebe, " + message.getFrom().getResource())

	def cmd_dobre(self, cl, message, args):
		if len(args.split()) >= 1:
			self.conf_message(message.getFrom(), u"Dobre " + args.split()[0] + u" aj tebe, " + message.getFrom().getResource())

	def cmd_dobrou(self, cl, message, args):
		if len(args.split()) >= 1:
			self.conf_message(message.getFrom(), u"Dobrou " + args.split()[0] + u" aj tobě, " + message.getFrom().getResource())

	def cmd_dobry(self, cl, message, args):
		if len(args.split()) >= 1:
			self.conf_message(message.getFrom(), "Dobry " + args.split()[0] + " aj tebe, " + message.getFrom().getResource())

#	def cmd_koule(self, cl, message, args):
#		self.conf_message(message.getFrom(), u"Radšej použí krychli: !krychle "+args+" ;)")

#        def cmd_say(self, cl, message, args):
#                """!say <heslo> <komu> <co>"""
#                print "say command detected"
#                params = args.split()
#                if params[0] == "apophysovo_heslo":
#                        if params[1] == "<null>":
#                                text = ""
#                        else:
#                                text = "%s:" % params[1]
#                        for word in params[2:]:
#                                text += " %s" % word
#                        self.conf_message(message.getFrom(), text)
#

	def cmd_vyber(self, cl, message, args):
		if args.strip() == "":
			self.conf_message(message.getFrom(), 'Terc!')
		elif args.split()[0] == "ist_spat" and args.split()[1] == "programovat":
			self.conf_message(message.getFrom(), 'Moj vyber je: Do Terca na pivo')
		elif args.split()[0] == "programovat" and args.split()[1] == "ist_spat":
			self.conf_message(message.getFrom(), 'Moj vyber je: Do Terca na pivo')
		elif args.strip() != "":
			self.conf_message(message.getFrom(), u'Môj výber je: '+random.choice(args.split()))


	def cmd_ruleta(self, cl, message, args):
		res = random.randint(0, 5)
		if args == "":
			nick = message.getFrom().getResource()
		else:
			nick = args

		if res == 0:
			msg = ["%s is dead!"]
		else:
			msg = ["%s survives!"]

		if args == "/me" or args == "/kick" or args == "!gg" or args == "!google" or args == "!lamer" or args == "!vtip":
			nick = message.getFrom().getResource()
			msg = ["%s: Neskusaj sprostosti!"]

		self.conf_message(message.getFrom(), random.choice(msg)%(nick))

		if res == 0:
#Kill him!
			#xmpp.protocol.Iq('set', 'http://jabber.org/protocol/muc#admin', {'id':'blaBla'}, '1bit_vut@conf.netlab.cz', None, [], NS_CLIENT, )
			#  def __init__(self, typ=None, queryNS=None, attrs={}, to=None, frm=None, payload=[], xmlns=NS_CLIENT, node=None): 
			cl.send('''<iq type="set" to="1bit_vut@conf.netlab.cz" id="ab1ea" >
<query xmlns="http://jabber.org/protocol/muc#admin">
<item nick="'''+nick+'''" role="none" />
</query>
</iq>''')

		
	def cmd_kedy(self, cl, message, args):
		if args == "isiel polo do postele?":
			if self.poloLastActivity:
				lastDay = self.poloLastActivity.date()
				today = datetime.today().date()
				yesterday = today - timedelta(1)

				if lastDay == today:
					day = ""
				elif lastDay == yesterday:
					day = "včera "
				else:
					day = lastDay.strftime("%d. %m. ")

				time = self.poloLastActivity.strftime("%H:%M")
				poloMessage = u"Polo tu niečo kecal naposledy %s%s" % (day, time)
			else:
				poloMessage = u"Čéče, ja ti neviem :-/"

			self.conf_message(message.getFrom(), poloMessage)

#		polovolovina
	def cmd_sudo(self, cl, message, args):
		sender = message.getFrom().getResource()
		if args == "make me a sandwich":
			self.conf_message(message.getFrom(), "%s: Nedas si radeji toust?"%sender)

	def cmd_set(self, cl, message, args):
		sender = message.getFrom().getResource()
                try:
                    if len(args.split()) >= 2:
                            key = args.split()[0]
                            value = args[args.find(" ")+1:]
                            
                            self._database.db_insert(key, value)
                            # pole[args.split()[0]] = args[args.find(" ")+1:]
                            msgs = [u"%s: acknowledged"%sender, u"%s: got it"%sender, u"%s: ok"%sender, u"%s: will be done"%sender, u"%s: mas to mit"%sender, u"%s: as you wish"%sender, u"%s: sir, yes sir!"%sender, u"%s: understood"%sender]
                            self.conf_message(message.getFrom(), random.choice(msgs))
                    else:
                        raise IOError("POZOR! Odchytena chyba vseobecneho charakteru.")
                except IOError, err:
                    self.conf_message(message.getFrom(), str(err))


	def cmd_get(self, cl, message, args):
		sender = message.getFrom().getResource()
		if len(args.split()) >= 1:
                        res = self._database.db_select(args.split()[0])
                        
                        self.conf_message(message.getFrom(), "%s: %s" % (sender, res, ))
			#        self.conf_message(message.getFrom(), "%s: %s"%(sender, msg))
                        #if pole.has_key(args.split()[0]):
			#	self.conf_message(message.getFrom(), "%s: %s"%(sender,pole[args.split()[0]]))
			# else:
			#	self.conf_message(message.getFrom(), u"Tak toto klucove slovo nepoznam, sorry")


	def cmd_unset(self, cl, message, args):
		sender = message.getFrom().getResource()
                splitted = args.split()
                try:
                    if len(splitted) == 1:
                        self._database.db_delete(splitted[0])
                    elif len(splitted) > 1:
                        self._database.db_delete(splitted[0], int(splitted[1]))
                    else:
                        return
                    self.conf_message(message.getFrom(), "%s: %s" % (sender, "vymazane"))
                except (KeyError, IndexError), err:
                    self.conf_message(message.getFrom(), "%s: %s" % (sender, str(err)))
                except (ValueError), err:
                    self.conf_message(message.getFrom(), "%s: %s" % (sender, "Index ide druhy. Konecne."))
        
        
        def cmd_unget(self, cl, message, args):
            self.cmd_unset(cl, message, args)

#	def cmd_unget(self, cl, message, args):
#	    sender = message.getFrom().getResource()
#           if pole.has_key(args.split()[0]):
#                self.conf_message(message.getFrom(), "%s: Polozka pod klucom \"%s\" bola uspesne zmazana"%(sender, args.split()[0]))
#                del pole[args.split()[0]]
#            else:
#                self.conf_message(message.getFrom(), "%s: Takyto kluc zatial nebol ulozeny." %sender)

	def cmd_find(self, cl, message, args):
		sender = message.getFrom().getResource()
                self.conf_message(message.getFrom(), "%s: funkciu nepouzivat." % (sender,))
		if pole.has_key(args.split()[0]):
			self.conf_message(message.getFrom(), "%s: Kluc \"%s\" existuje :-P"%(sender, args.split()[0]))
		else:
			self.conf_message(message.getFrom(), "%s: Kluc \"%s\" bohuzial / vdakabohu neexistuje"%(sender, args.split()[0]))

# apopicovina
        def cmd_cas(self, cl, message, args):
            halfhour = 1800.0
            sender = message.getFrom().getResource()
            if self.game is None or self.game + halfhour < time():
                self.game = time()
                msg = random.choice(["prehrala som", "iltg", "ja uz nechcem prehravat :("])
            elif self.game + halfhour > time():
                msg = random.choice(["daj pokoj", "nechaj ma", None, None, None, None ])
            else:
                pass
            if msg is not None:
                self.conf_message(message.getFrom(), "%s: %s" % (sender, msg))
            


#		polovina end

	def cmd_good(self, cl, message, args):
		res = random.randint(0, 5)
		sender = message.getFrom().getResource()
		if args == "":
			self.conf_message(message.getFrom(), u"Koho chceš pochváliť?")
			return

		nick = args

		if nick == sender:
			self.conf_message(message.getFrom(), u"Looser, neďakuj sám sebe!")
			return

		if nick == "iyo":
			msgs = [u"%s posiela půlitr studenej kofoly pre iyáčka"%sender, u"%s hádže iyimu kostkový cukr (ktorý má veľmi rád!)"%sender]
		elif nick == "weeto":
			msgs = [u"%s si pochutnava na bananovem kravikovi"%nick]
		elif nick == "/me":
			msgs = [u"Neskusaj sprostosti!"]
		elif nick == "!gg":
			msgs = [u"Neskusaj sprostosti!"]
		else:
			msgs = [u"%s dostáva duplák kozla"%nick, u"%s si pochutnáva na radkovi"%nick, u"%s s červeňou v tvári ďakuje :-["%nick]

		self.conf_message(message.getFrom(), random.choice(msgs))


	def cmd_timer(self,cl, message, args):
		t1 = round(mktime(datetime(2009, 2, 9, 9, 50).timetuple()))
		msg_end = "Koniec... :-P"
			
		#print "'%s'" % args
		t2 = round(time())
		delta = t1-t2
		if(delta < 0):
			msg = msg_end
		else:
			#print delta

			h = floor(delta/3600)
			delta = delta - h*3600
			m = floor(delta / 60)
			s = floor(delta - 60*m)

			cas = ""
			if h > 0:
				cas = cas + "%dh"%(h)
			cas = cas + " %dm %ds"%(m, s)

			msg = "Do konca IPR zostáva %s! ;)" % cas
		
		self.conf_message(message.getFrom(), msg);

        def log(self, message):
                print "Log: %s" % message

#  
#   Vymazat? -- Ultimatne mrtvy kod. Apo.
#
#!!!!!!!!!!!!!!!!!!!!straiki!!!!!!!!!!!!!!!!!!!!!!!!!!!!
#	def cmd_deadline(self,cl, message, args):
#    		t1 = round(mktime(datetime(2010, 5, 9, 23, 59).timetuple()))
#    		msg_end = u"A je to v prdeli, definitivne."
#                        
#    		#print "'%s'" % args
#    		t2 = round(time())
#    		delta = t1-t2
#    		if(delta < 0):
#        		msg = msg_end
#    		else:
#        		#print delta
#			d = floor(delta/(24*3600))
#			delta = delta - d*24*3600
#        		h = floor(delta/3600)
#        		delta = delta - h*3600
#        		m = floor(delta / 60)
#        		s = floor(delta - 60*m)
#
#        		cas = ""
#        		if d > 0:
#            			cas = cas + "%dd "%(d)
#			if h > 0:
#            			cas = cas + "%dh "%(h)
#        		cas = cas + "%dm %ds"%(m, s)
#
#        		msg = u"Este mame %s casu, makajte volove!!" % cas
#                
#    		self.conf_message(message.getFrom(), msg);
#
#	def cmd_ifj(self,cl, message, args):
#    		t1 = round(mktime(datetime(2010, 1, 11, 11, 00).timetuple()))
#    		msg_end = u"Zkouška už byla.. :-|"
#                        
#    		#print "'%s'" % args
#    		t2 = round(time())
#    		delta = t1-t2
#    		if(delta < 0):
#        		msg = msg_end
#    		else:
#        		#print delta
#			d = floor(delta/(24*3600))
#			delta = delta - d*24*3600
#        		h = floor(delta/3600)
#        		delta = delta - h*3600
#        		m = floor(delta / 60)
#        		s = floor(delta - 60*m)
#
#        		cas = ""
#         		if d > 0:
#            			cas = cas + "%dd "%(d)
#	       		if h > 0:
#            			cas = cas + "%dh "%(h)
#        		cas = cas + "%dm %ds"%(m, s)
#
#        		msg = u"Do zkoušky z IFJ zbývá %s! Uč se!" % cas
#                
#    		self.conf_message(message.getFrom(), msg);
#
#	def cmd_inp(self,cl, message, args):
#    		t1 = round(mktime(datetime(2010, 1, 13, 12, 00).timetuple()))
#    		msg_end = u"Zkouška už byla.. :-|"
#                        
#    		#print "'%s'" % args
#    		t2 = round(time())
#    		delta = t1-t2
#    		if(delta < 0):
#        		msg = msg_end
#    		else:
#        		#print delta
#			d = floor(delta/(24*3600))
#			delta = delta - d*24*3600
#        		h = floor(delta/3600)
#        		delta = delta - h*3600
#        		m = floor(delta / 60)
#        		s = floor(delta - 60*m)
#
#        		cas = ""
#          		if d > 0:
#            			cas = cas + "%dd "%(d)
#	       		if h > 0:
#            			cas = cas + "%dh "%(h)
#        		cas = cas + "%dm %ds"%(m, s)
#
#        		msg = u"Do zkoušky z INP zbývá %s! Uč se!" % cas
#                
#    		self.conf_message(message.getFrom(), msg);
#
#	def cmd_ial(self,cl, message, args):
#    		t1 = round(mktime(datetime(2010, 1, 18, 7, 00).timetuple()))
#    		msg_end = u"Zkouška už byla.. :-|"
#                        
#    		#print "'%s'" % args
#    		t2 = round(time())
#    		delta = t1-t2
#    		if(delta < 0):
#        		msg = msg_end
#    		else:
#        		#print delta
#			d = floor(delta/(24*3600))
#			delta = delta - d*24*3600
#        		h = floor(delta/3600)
#        		delta = delta - h*3600
#        		m = floor(delta / 60)
#        		s = floor(delta - 60*m)
#
#        		cas = ""
#           		if d > 0:
#            			cas = cas + "%dd "%(d)
#	       		if h > 0:
#            			cas = cas + "%dh "%(h)
#        		cas = cas + "%dm %ds"%(m, s)
#
#		        msg = u"Do zkoušky z IAL zbývá %s! Uč se!" % cas
#                
#    		self.conf_message(message.getFrom(), msg);
#
#	def cmd_iss(self,cl, message, args):
#    		t1 = round(mktime(datetime(2010, 1, 20, 7, 00).timetuple()))
#    		msg_end = "Zkouška už byla.. :-|"
#                        
#    		#print "'%s'" % args
#   		t2 = round(time())
#    		delta = t1-t2
#    		if(delta < 0):
#        		msg = msg_end
#    		else:
#        		#print delta
#			d = floor(delta/(24*3600))
#			delta = delta - d*24*3600
#        		h = floor(delta/3600)
#        		delta = delta - h*3600
#        		m = floor(delta / 60)
#        		s = floor(delta - 60*m)
#
#        		cas = ""
#            		if d > 0:
#            			cas = cas + "%dd "%(d)
#	       		if h > 0:
#            			cas = cas + "%dh "%(h)
#        		cas = cas + "%dm %ds"%(m, s)
#
#        		msg = u"Do zkoušky z ISS zbývá %s! Uč se!" % cas
#                
#    		self.conf_message(message.getFrom(), msg);

#!!!!!!!!!!!!!!!!!!!!straiki!!!!!!!!!!!!!!!!!!!!!!!!!!!!

	def terc(self, cl, event):
		"""Hidden feature of nora - when they come from Terč"""
		user = event.getFrom().getResource()
                monitored = ['polo']
		#monitored = ['iyo', 'polo', 'Tommino', 'straiki', 'Olinka', 'Zuzka', 'Zuzanka', 'ondrush', 'apophys']

		if not user in monitored:
			return

		t = localtime()
		midnight = mktime(t)
		midnight = midnight - midnight % (24*60*60)

		if 1 <= t.tm_hour and t.tm_hour <= 3 and (not self.lastSaid.has_key(user) or self.lastSaid[user] < midnight ):
			msgs = [u'Zase z Terča, čo?', u'Že ťa to baví sa niekde vonku flákať ;)', u'Dúfam, že zajtra nemáte nič náročného!', u'Projekty už máte hotové?:-/', u'Príde informatik z hospody domov a hneď je už za kompom.... Tá dnešná mládež...', u'Dúfam, že zajtra nemáte nič prestížneho!']
			self.conf_message(event.getFrom(), "%s: %s"%(user, random.choice(msgs)));



		self.lastSaid[user] = time()

	def self_highlight(self, cl, event):
		user = event.getFrom().getResource()

		if user in ['taxator']:
			return

		body = event.getBody()
		# Small bug? =-O
		if not body:
			return

		names = ['nora', 'noro', 'nore', 'Nora', 'Noro', 'Nore', 'nory', 'Nory', 'Noru', 'noru']

		for name in names:
			if name in body:
				msgs = [u'Čo sa deje?', u'Horí?', u'Nechaj ma!', u'Nemám na to náladu!', u'Áno, miláčik? :-*', u'Zase otravuješ?', u'Nespamuj, prosím!']
				self.conf_message(event.getFrom(), "%s: %s"%(user, random.choice(msgs)));
				return


	poloNicks = ['polo', 'ctvrtka', '1/2', '0.5', '2^-1']

	def incomming_message(self, cl, event):
		# Dočasné riešenie!!!!!
		if event.getType() != 'groupchat':
			return

		# Preskakujeme stare spravy
		if event.getTag("x", namespace="jabber:x:delay"):
			return 

		body = event.getBody()
		user = event.getFrom().getResource()

		if user == self.nick:
			return

		self.terc(cl, event)

		if user in self.poloNicks:
			self.poloLastActivity = datetime.now()

		if not body or not body.startswith(self.command_mark):
			return

		if ' ' in body:
			command, args = body.split(' ', 1)
		else:
			command, args = body, ''

		command = command.lower()

		
		(response, pm) = self.automaticMessages.check(body[len(self.command_mark):], user)

		if self.command.has_key(command):
			self.command[command] (cl, event, args)
		elif response:
				if pm:
					self.chat_pm_message(event.getFrom(), response)
				else:
					self.chat_message(event.getFrom(), response)
		else:
			self.self_highlight(cl, event)


	def presence(self, cl, event):
		room=event.getFrom().getStripped()
	    	nick=event.getFrom().getResource()
		
	    	#if event.getType()!='unavailable':
			#print u"%s sa prihlasil\n" % nick
		#else:
			#print u"%s sa odhlasil\n" % nick

        def connect(self):
		if self.cl == None:
			cl = xmpp.Client(self.jid.getDomain(), debug=[])
			if not cl.connect():
				self.log('Unable to connect to server.')
				return None

			self.res = self.jid.getResource()
			if self.res == '':
				self.res = "noraBot"
				self.log('Setting resource to default `noraBot`')

			if not cl.auth(self.jid.getNode(), self.passwd, self.res):
				self.log('Unable to authorize')
				return None
			
			for roomName, roomPasswd, roomNick in self.rooms:
				print "jdme na vec"
				print "###", roomName
				p=xmpp.Presence(to='%s'%(roomName + "/" + roomNick))
				p.setTag('x',namespace=xmpp.NS_MUC).setTagData('password',roomPasswd) # mame nebo nemame heslo?
				self.log('Connected to %s.'%roomName)
				cl.send(p)

			cl.RegisterHandler( 'message', self.incomming_message)
			cl.RegisterHandler( 'presence', self.presence)
			cl.sendInitPresence()

			self.cl = cl
			return self.cl
		else:
			return self.cl

	def chat_message(self, sender, text):
		conf =  sender.getStripped()
		self.connect().send(xmpp.Message(conf, text, 'groupchat'))

	def chat_pm_message(self, sender, text):
		self.connect().send(xmpp.Message(sender, text, 'chat'))

	def sendMsgs(self):
		jid = xmpp.protocol.JID("1bit_vut@conf.netlab.cz")
		fileName="msgs.txt"
		f = open(fileName, "r")
		for line in f.readlines():
			print "niečo posielam - "+line
			self.chat_message(jid, line)
		f.close()

		f = open(fileName, "w")
		f.close()


	def start_up(self):
		for roomName, roomPassword, roomNick in self.rooms:
			msgs = [u"A som zase tu :-)", u"Pekné kecanie"]

			self.conf_message(xmpp.protocol.JID(roomName), random.choice(msgs))

	def finish(self):
		for roomName, roomPassword, roomNick in self.rooms:
			msgs = [u"Čauko", u"Ja sa čochvíľa vrátim!"]

			self.conf_message(xmpp.protocol.JID(roomName), random.choice(msgs))

	def serve(self):
		if self.connect():
			self.log('Bot start serving')
		else:
			self.log('Unable to start bot. Quiting')
			return

		self.start_up()

		while True:
			try:
				self.connect().Process(1)
				#self.sendMsgs()
				pass
			except KeyboardInterrupt:
				self.finish()
				self.log('Bot interrupted by user. Quiting.')
				self.connect().disconnect()
				break

# Configuration file
if len(sys.argv) >= 2:
	configFile = sys.argv[1]
else:
	configFile =os.path.expanduser("~/.norarc") # Default

bot = noraBot(configFile)
bot.serve()
